package org.atlas.framework.helper;

import org.atlas.framework.annotation.Inject;
import org.atlas.framework.util.ArrayUtil;
import org.atlas.framework.util.CollectionUtil;
import org.atlas.framework.util.MapUtil;
import org.atlas.framework.util.ReflectionUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;

/**
 * 依赖注入助手类
 *
 * Created by suxinjie on 2017/3/5.
 */
public class IocHelper {

    //FIXME 现在注入的都是单例的
    static {
        Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
        if (MapUtil.isNotEmpty(beanMap)) {
            for (Map.Entry<Class<?>, Object> entry : beanMap.entrySet()) {
                Class<?> beanClass = entry.getKey();
                Object beanInstance = entry.getValue();

                //获取bean的成员变量,查看是否有Inject注解
                Field[] beanFields = beanClass.getDeclaredFields();
                if(ArrayUtil.isNotEmpty(beanFields)) {
                    for (Field field : beanFields) {
                        if (field.isAnnotationPresent(Inject.class)) {
                            Class<?> interfaceClass = field.getType();
                            Class<?> implementClass = findImplementClass(interfaceClass);
                            if (implementClass != null) {
                                ReflectionUtil.setField(beanInstance, field, ReflectionUtil.newInstance(implementClass));
                            } else {
                                throw new RuntimeException("依赖注入失败! 类名:" + beanClass.getSimpleName() + ",字段名:" + interfaceClass.getSimpleName());
                            }
                        }
                    }
                }
            }
        }
    }

    public static Class<?> findImplementClass(Class<?> interfaceClass) {
        Class<?> implementsClass = interfaceClass;
        Set<Class<?>> implementsClassList = ClassHelper.getClassListBySuper(interfaceClass);
        if (CollectionUtil.isNotEmpty(implementsClassList)) {
            implementsClass = new ArrayList<>(implementsClassList).get(0);
        }

        return implementsClass;
    }

}
